﻿//-----------------------------------------------------------------------
// <copyright file="InMemoryTokenManager.cs" company="Andrew Arnott">
//     Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
using ej2social.DataAccess;

namespace ej2social.Library.DotNetOpenAuth
{
    public class InMemoryTokenManager : ITokenManager {

        public InMemoryTokenManager(string consumerKey, string consumerSecret) {
            this.ConsumerKey = consumerKey;
            this.ConsumerSecret = consumerSecret;
        }

        public string ConsumerKey { get; private set; }

        public string ConsumerSecret { get; private set; }

        #region ITokenManager Members

        public string GetConsumerSecret(string consumerKey) {
            if (consumerKey == this.ConsumerKey) {
                return this.ConsumerSecret;
            } else {
                throw new ArgumentException("Unrecognized consumer key.", "consumerKey");
            }
        }

        public string GetTokenSecret(string token) {
            using (var db = new ejDataContext())
            {
                return (from o in db.oauth_tokens
                        where o.token_key == token
                        select o.token_secret).SingleOrDefault();

            }
        }

        public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response) {
            using (var db = new ejDataContext())
            {
                oauth_token data = new oauth_token();
                data.token_secret = response.TokenSecret;
                data.token_key = response.Token;
                data.authorized = false;
                data.type = "request";
                db.oauth_tokens.InsertOnSubmit(data);
                db.SubmitChanges();
            }
        }

        /// <summary>
        /// Checks whether a given request token has already been authorized
        /// by some user for use by the Consumer that requested it.
        /// </summary>
        /// <param name="requestToken">The Consumer's request token.</param>
        /// <returns>
        /// True if the request token has already been fully authorized by the user
        /// who owns the relevant protected resources.  False if the token has not yet
        /// been authorized, has expired or does not exist.
        /// </returns>
        public bool IsRequestTokenAuthorized(string requestToken) {
            using (var db = new ejDataContext())
            {
                var tt = (from o in db.oauth_tokens
                          where o.token_key == requestToken
                          select o.authorized).Single();
                return tt;
            }
        }

        public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) 
        {
            using (var db = new ejDataContext())
            {
                var existing = (from o in db.oauth_tokens
                                where o.consumer_key == consumerKey && o.token_key == requestToken
                                select o).Single();

                existing.token_secret = accessTokenSecret;
                existing.token_key = accessToken;
                db.SubmitChanges();
            }
        }

        /// <summary>
        /// Classifies a token as a request token or an access token.
        /// </summary>
        /// <param name="token">The token to classify.</param>
        /// <returns>Request or Access token, or invalid if the token is not recognized.</returns>
        public TokenType GetTokenType(string token) {
            using (var db = new ejDataContext())
            {
                var tt = (from o in db.oauth_tokens
                          where o.token_key == token
                          select o.type).Single();
                switch (tt)
                {
                    case "request":
                        return TokenType.RequestToken;
                    case "access":
                        return TokenType.AccessToken;
                    default:
                        return TokenType.InvalidToken;
                }
            }
        }

        #endregion
    }
}